package com.cenxi.manage;

import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cenxi.common.constants.Constants;
import com.cenxi.common.dto.LoginUserDTO;
import com.cenxi.common.dto.req.LoginReqDTO;
import com.cenxi.common.util.JwtUtils;
import com.cenxi.common.util.SecurityUtils;
import com.cenxi.common.util.resp.Resp;
import com.cenxi.config.RedisService;
import com.cenxi.dao.domain.Account;
import com.cenxi.dao.service.AccountService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @Author cenxi
 * @Date 2023/8/16 17:33
 * @Version 1.0
 */
@Slf4j
@Component
public class ManageLoginService {
    @Autowired
    private AccountService accountService;
    @Autowired
    private RedisService redisService;

    static final String ACCOUNT_PWD_ERR_CNT_KEY = "account:pwd_err_cnt:";
    /**
     * 密码最大错误次数
     */
    static final int PASSWORD_MAX_RETRY_COUNT = 5;

    /**
     * 密码锁定时间，默认10（分钟）
     */
    static final long PASSWORD_LOCK_TIME = 10;

    public Resp<LoginUserDTO> login(LoginReqDTO data) {
        if (Objects.isNull(data.getAccount()) || Objects.isNull(data.getPassword())) {
            return Resp.error("参数有误");
        }
        Account account = accountService.getOne(new LambdaQueryWrapper<Account>()
                .eq(Account::getAccount, data.getAccount()));
        if (Objects.isNull(account)) {
            return Resp.error("账户不存在");
        }

        if (!account.getPassword().equals(new MD5().digestHex16(data.getPassword()))) {
            Long increment = redisService.increment(ACCOUNT_PWD_ERR_CNT_KEY + data.getAccount(), PASSWORD_LOCK_TIME, TimeUnit.MINUTES);
            if (increment > PASSWORD_MAX_RETRY_COUNT) {
                return  Resp.error("密码错误，请"+ PASSWORD_LOCK_TIME +"分钟后重试");
            }
            return Resp.error("密码错误,剩余: " + (PASSWORD_MAX_RETRY_COUNT - increment) + "次登录机会");
        }else {
            // 清除错误重试次数
            redisService.deleteObject(ACCOUNT_PWD_ERR_CNT_KEY + data.getAccount());
        }
        // 校验账户状态
        if (account.getState() == Constants.DISABLE) {
            return Resp.error("账户已被封禁,请联系管理员");
        }
        // 生成token返回前端
        LoginUserDTO loginUserDTO = new LoginUserDTO();
        loginUserDTO.setUserId(String.valueOf(account.getId()));
        loginUserDTO.setUserName(account.getNickName());
        loginUserDTO.setLoginTime(System.currentTimeMillis()/1000);
        Map<String, Object> tokenDTO = JwtUtils.createTokenDTO(loginUserDTO);
        String accessToken = (String) tokenDTO.get("access_token");
        loginUserDTO.setToken(accessToken);
        // 添加token信息到缓存中
        redisService.setCacheObject(Constants.LOGIN_TOKEN_KEY + accessToken, loginUserDTO, Constants.OUT_TIME, TimeUnit.SECONDS);
        account.setLoginDate(new Date());
        accountService.updateById(account);
        return Resp.succeed(loginUserDTO);
    }

    public Resp<Void> logout() {
        String token = SecurityUtils.getToken();
        if (StringUtils.isNotEmpty(token)) {
            // 删除用户缓存记录
            redisService.deleteObject(Constants.LOGIN_TOKEN_KEY + token);
            return Resp.succeed();
        }
        return Resp.error("token不存在");
    }
}
